package com.fis.vaadin;

import java.util.Vector;

import com.fis.vaadin.component.TableContainer;
import com.fis.vaadin.define.Layout;
import com.fis.vaadin.define.Properties;
import com.fis.vaadin.define.Sections;
import com.fis.vaadin.utils.StringUtil;
import com.fss.dictionary.DictionaryNode;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Accordion;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.VerticalSplitPanel;

import eu.livotov.tpt.i18n.TM;

public class LayoutBuilderImpl implements LayoutBuilder {

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public ComponentContainer buildFormLayout(ComponentContainer form,
			VaadinFormData formData, DictionaryNode dictionaryNode)
			throws Exception {

		Vector vtLayoutElements = dictionaryNode.getChildList();

		for (int i = 0; i < vtLayoutElements.size(); ++i) {

			DictionaryNode dnLayoutElement = (DictionaryNode) vtLayoutElements
					.elementAt(i);
			Component cmp = null;
			String strType = dnLayoutElement.mstrName.toLowerCase();
			String strWidth = dnLayoutElement
					.getStringIgnoreCase(Properties.WIDTH);
			String strHeight = dnLayoutElement
					.getStringIgnoreCase(Properties.HEIGHT);

			if (strType.equals(Properties.LAYOUT_CONTROL)) {

				cmp = createControlLayout(form, formData, dnLayoutElement);

			} else if (strType.equals(Properties.LAYOUT_CONTROL_BUTTON)) {

				cmp = createControlButtonLayout(form, formData, dnLayoutElement);

			} else if (strType.equals(Properties.LAYOUT_LABEL)) {

				cmp = createLabelLayout(form, formData, dnLayoutElement);

			} else if (strType.equals(Properties.LAYOUT_PANEL)) {

				cmp = createPanelLayout(form, formData, dnLayoutElement);

			} else if (strType.equals(Properties.LAYOUT_SCROLL_PANE)) {

				cmp = createScrollLayout(form, formData, dnLayoutElement);

			} else if (strType.equals(Properties.LAYOUT_TABLE_CONTAINER)) {

				cmp = createTableContainerLayout(form, formData,
						dnLayoutElement);

			} else {
				throw new UnsupportedException(String.format(
						"Layout with type %s has not been supported\n\tAt: %s",
						strType, dnLayoutElement.getTrace()));
			}

			if (!strType.equals(Properties.LAYOUT_CONTROL)) {

				String strName = dnLayoutElement.getValue();

				formData.getVtLayoutList().addElement(cmp);
				formData.getMapLayoutList().put(strName, cmp);
				formData.getMapLayoutDefinition().put(strName, dnLayoutElement);

			}

			if (!strWidth.equals(""))
				cmp.setWidth(strWidth);

			if (!strHeight.equals(""))
				cmp.setHeight(strHeight);

		}

		return form;

	}

	@SuppressWarnings("rawtypes")
	@Override
	public Component createPanelLayout(ComponentContainer form,
			VaadinFormData formData, DictionaryNode dictionaryNode)
			throws Exception {

		String strType = dictionaryNode.getValue().toLowerCase();
		ComponentContainer layout = null;
		DictionaryNode dnLayout = dictionaryNode
				.getChildIgnoreCase(Sections.DEFINE_LAYOUT);

		if (strType.equals(Layout.GRID)) {

			int columns = 0;
			int rows = 0;
			boolean spacing = false;
			boolean marginTop = false;
			boolean marginRight = false;
			boolean marginBottom = false;
			boolean marginLeft = false;
			String strValue[];

			columns = StringUtil.parseInt(dictionaryNode
					.getStringIgnoreCase(Properties.COLUMN));
			rows = StringUtil.parseInt(dictionaryNode
					.getStringIgnoreCase(Properties.ROW));

			spacing = StringUtil.parseBoolean(dictionaryNode
					.getStringIgnoreCase(Properties.ALLOW_SPACING));

			strValue = dictionaryNode.getStringIgnoreCase(Properties.MARGIN)
					.split(Properties.SEPARATE_SYMBOL);

			if (columns == 0 && rows == 0)
				layout = new GridLayout();
			else
				layout = new GridLayout(columns, rows);

			// get margin defines
			for (String str : strValue) {

				if (str.equalsIgnoreCase(Properties.TOP))
					marginTop = true;
				else if (str.equalsIgnoreCase(Properties.RIGHT))
					marginRight = true;
				else if (str.equalsIgnoreCase(Properties.BOTTOM))
					marginBottom = true;
				else if (str.equalsIgnoreCase(Properties.LEFT))
					marginLeft = true;

			}

			((GridLayout) layout).setSpacing(spacing);
			((GridLayout) layout).setMargin(marginTop, marginRight,
					marginBottom, marginLeft);

		} else if (strType.equals(Layout.SPLIT)) {

			Panel leftPanel = null;
			Panel rightPanel = null;

			int splitPosition = StringUtil.parseInt(dictionaryNode
					.getStringIgnoreCase(Properties.SPLIT_POSITION));

			String strOrientation = dictionaryNode
					.getStringIgnoreCase(Properties.DEFINE_ORIENTATION);

			if (strOrientation != null
					&& strOrientation
							.equalsIgnoreCase(Properties.SPLIT_ALIGN_HORIZONTAL)) {

				layout = new HorizontalSplitPanel();

				if (splitPosition != 0)
					((HorizontalSplitPanel) layout)
							.setSplitPosition(splitPosition);

			} else {

				layout = new VerticalSplitPanel();

				if (splitPosition != 0)
					((VerticalSplitPanel) layout)
							.setSplitPosition(splitPosition);

			}

			// dividerLocation?

			DictionaryNode dnLeftComponent = (DictionaryNode) dictionaryNode
					.getChildIgnoreCase(Properties.LEFT_LAYOUT);
			DictionaryNode dnRightComponent = (DictionaryNode) dictionaryNode
					.getChildIgnoreCase(Properties.RIGHT_LAYOUT);

			// building left layout
			if (dnLeftComponent != null) {

				leftPanel = new Panel();

				buildFormLayout(leftPanel, formData, dnLeftComponent);

				// add left layout to container
				layout.addComponent(leftPanel);

			}

			if (dnRightComponent != null) {

				rightPanel = new Panel();

				buildFormLayout(rightPanel, formData, dnRightComponent);

				// add right layout to container
				layout.addComponent(rightPanel);

			}

		} else if (strType.equals(Layout.TABS)) {

			layout = new TabSheet();
			ComponentContainer tab;
			String strTitle;
			String strIcon;

			Vector vtLayoutElements = dictionaryNode.getChildList();

			for (int i = 0; i < vtLayoutElements.size(); ++i) {

				DictionaryNode dnLayoutElement = (DictionaryNode) vtLayoutElements
						.elementAt(i);

				if (dnLayoutElement.mstrName.equalsIgnoreCase(Properties.TAB)) {

					tab = new VerticalLayout();
					layout.addComponent(tab);

					strTitle = dnLayoutElement
							.getStringIgnoreCase(Properties.TITLE);
					strIcon = dnLayoutElement
							.getStringIgnoreCase(Properties.ICON);

					((TabSheet) layout).getTab(tab)
							.setCaption(TM.get(strTitle));

					if (!strIcon.equals(""))
						((TabSheet) layout).getTab(tab).setIcon(
								new ThemeResource(strIcon));

					// build sub container
					DictionaryNode subContainer = dnLayoutElement
							.getChildIgnoreCase(Sections.DEFINE_LAYOUT);

					if (subContainer != null)
						buildFormLayout(tab, formData, subContainer);

				}
			}

		} else if (strType.equals(Layout.ACCORDION)) {

			layout = new Accordion();
			ComponentContainer tab;
			String strTitle;
			String strIcon;

			Vector vtLayoutElements = dictionaryNode.getChildList();

			for (int i = 0; i < vtLayoutElements.size(); ++i) {

				DictionaryNode dnLayoutElement = (DictionaryNode) vtLayoutElements
						.elementAt(i);

				if (dnLayoutElement.mstrName.equalsIgnoreCase(Properties.TAB)) {

					tab = new VerticalLayout();
					layout.addComponent(tab);

					strTitle = dnLayoutElement
							.getStringIgnoreCase(Properties.TITLE);
					strIcon = dnLayoutElement
							.getStringIgnoreCase(Properties.ICON);

					((TabSheet) layout).getTab(tab)
							.setCaption(TM.get(strTitle));

					if (!strIcon.equals(""))
						((TabSheet) layout).getTab(tab).setIcon(
								new ThemeResource(strIcon));

					// build sub container
					DictionaryNode subContainer = dnLayoutElement
							.getChildIgnoreCase(Sections.DEFINE_LAYOUT);

					if (subContainer != null)
						buildFormLayout(tab, formData, subContainer);

				}
			}

		} else {

			// default layout
			layout = new VerticalLayout();

		}

		addComponentToPane(form, layout, dictionaryNode, 0, 0, 1, 1, 0d, 0d, 0,
				0, 2, 2, 2, 2, 10, 0);

		if (dnLayout != null) {

			buildFormLayout(layout, formData, dnLayout);

		}

		return layout;
	}

	@Override
	public Component createControlLayout(ComponentContainer form,
			VaadinFormData formData, DictionaryNode dictionaryNode)
			throws Exception {

		String strName = dictionaryNode.getValue();
		Component cmp = (Component) formData.getMapControlList().get(strName);

		if (cmp == null)
			throw new NotfoundException(String.format(
					"No component with name %s\n\tAt: %s", strName,
					dictionaryNode.getTrace()));

		addComponentToPane(form, cmp, dictionaryNode, 0, 0, 1, 1, 1d, 0d, 0, 0,
				2, 2, 2, 2, 10, 2);

		return cmp;
	}

	@Override
	public Component createControlButtonLayout(ComponentContainer form,
			VaadinFormData formData, DictionaryNode dictionaryNode)
			throws Exception {

		// PanelControlButton?

		return null;
	}

	@Override
	public Component createLabelLayout(ComponentContainer form,
			VaadinFormData formData, DictionaryNode dictionaryNode)
			throws Exception {

		Component cmp = new Label();
		String strResource = dictionaryNode
				.getStringIgnoreCase(Properties.RESOURCE);
		DictionaryNode dnIcon = dictionaryNode
				.getChildIgnoreCase(Properties.ICON);

		if (!strResource.equals(""))
			cmp.setCaption(TM.get(strResource));

		if (dnIcon != null) {
			// example: icons/16/cancel.png
			cmp.setIcon(new ThemeResource(dnIcon.getValue()));
		}

		addComponentToPane(form, cmp, dictionaryNode, 0, 0, 1, 1, 1d, 0d, 0, 0,
				2, 2, 2, 2, 10, 2);

		return cmp;
	}

	@Override
	public Component createScrollLayout(ComponentContainer form,
			VaadinFormData formData, DictionaryNode dictionaryNode)
			throws Exception {

		// String strName = dictionaryNode.getValue();
		// ComponentContainer cmp = new VerticalLayout();
		// Panel innerPanel = new Panel();
		//
		// Component innerCmp = (Component) formData.getMapContronList().get(
		// strName);
		//
		// if (innerCmp == null)
		// throw new NotfoundException(String.format(
		// "No component with name %s\n\tAt: %s", strName,
		// dictionaryNode.getTrace()));
		//
		// innerPanel.setSizeUndefined();
		//
		// addComponentToPane(innerPanel, innerCmp, dictionaryNode, 0, 0, 1, 1,
		// 1d, 0d, 0, 0, 2, 2, 2, 2, 10, 2);
		//
		// addComponentToPane(form, cmp, dictionaryNode, 0, 0, 1, 1, 1d, 0d, 0,
		// 0,
		// 2, 2, 2, 2, 10, 2);
		//
		// return cmp;

		return null;
	}

	@Override
	public Component createTableContainerLayout(ComponentContainer form,
			VaadinFormData formData, DictionaryNode dictionaryNode)
			throws Exception {

		String strName = dictionaryNode.getValue();
		// String strActionClass = dictionaryNode
		// .getStringIgnoreCase(Properties.ACTION_PANEL_CLASS);
		Component cmp = (Component) formData.getMapControlList().get(strName);

		if (cmp == null)
			throw new NotfoundException(String.format(
					"No component with name %s\n\tAt: %s", strName,
					dictionaryNode.getTrace()));

		TableContainer tableContainer = new TableContainer((Table) cmp);

		// if (!strActionClass.equals(""))
		// tableContainer.setActionPanel((HorizontalLayout) Class.forName(
		// strActionClass).newInstance());

		addComponentToPane(form, tableContainer, dictionaryNode, 0, 0, 1, 1,
				1d, 0d, 0, 0, 2, 2, 2, 2, 10, 2);

		return tableContainer;
	}

	private void addComponentToPane(ComponentContainer contentPane,
			Component component, DictionaryNode dictionaryNode, int x, int y,
			int w, int h, double wx, double wy, int px, int py, int mt, int ml,
			int mb, int mr, int iAnchor, int iFill) throws Exception {

		String strAlignment = dictionaryNode
				.getStringIgnoreCase(Properties.ALIGN);

		contentPane.addComponent(component);

		if (!strAlignment.equals("")) {

			if (contentPane instanceof AbstractOrderedLayout
					|| contentPane instanceof GridLayout) {

				if (strAlignment.equalsIgnoreCase(Properties.ALIGN_TOP_CENTER))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.TOP_CENTER);
				else if (strAlignment
						.equalsIgnoreCase(Properties.ALIGN_TOP_LEFT))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.TOP_LEFT);
				else if (strAlignment
						.equalsIgnoreCase(Properties.ALIGN_TOP_RIGHT))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.TOP_RIGHT);
				else if (strAlignment
						.equalsIgnoreCase(Properties.ALIGN_MIDDLE_CENTER))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.MIDDLE_CENTER);
				else if (strAlignment
						.equalsIgnoreCase(Properties.ALIGN_MIDDLE_LEFT))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.MIDDLE_LEFT);
				else if (strAlignment
						.equalsIgnoreCase(Properties.ALIGN_MIDDLE_RIGHT))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.MIDDLE_RIGHT);
				else if (strAlignment
						.equalsIgnoreCase(Properties.ALIGN_BOTTOM_CENTER))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.BOTTOM_CENTER);
				else if (strAlignment
						.equalsIgnoreCase(Properties.ALIGN_BOTTOM_LEFT))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.BOTTOM_LEFT);
				else if (strAlignment
						.equalsIgnoreCase(Properties.ALIGN_BOTTOM_RIGHT))
					((AbstractOrderedLayout) contentPane)
							.setComponentAlignment(component,
									Alignment.BOTTOM_RIGHT);

			}

		}
	}
}
